/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable no-template-curly-in-string */
import {
  computed,
  defineComponent,
  PropType,
  resolveComponent,
  h,
  VNode,
} from 'vue';
import { useNamespace } from '@ibiz-template/vue3-util';
import { ISearchBarFilter } from '@ibiz/model-core';
import {
  IFilterNodeField,
  SearchBarFilterController,
  ValueOP,
} from '@ibiz-template/runtime';
import { FilterSearchBarController } from '../../filter-search-bar.controller';
import { IBizInput } from '../input/input';
import './filter-item.scss';

export type FieldInfo = {
  name: string;
  label: string;
  valueOPs: string[];
};

/**
 * 操作模式
 */
export const FilterModes = [
  { valueOP: ValueOP.EQ, label: '等于(=)' },
  { valueOP: ValueOP.NOT_EQ, label: '不等于(<>)' },
  { valueOP: ValueOP.GT, label: '大于(>)' },
  { valueOP: ValueOP.GT_AND_EQ, label: '大于等于(>=)' },
  { valueOP: ValueOP.LT, label: '小于(<)' },
  { valueOP: ValueOP.LT_AND_EQ, label: '小于等于(<=)' },
  { valueOP: ValueOP.IS_NULL, label: '值为空(Nil)' },
  { valueOP: ValueOP.IS_NOT_NULL, label: '值不为空(NotNil)' },
  { valueOP: ValueOP.IN, label: '值在范围中(In)' },
  { valueOP: ValueOP.NOT_IN, label: '值不在范围中(NotIn)' },
  { valueOP: ValueOP.LIKE, label: '文本包含(%)' },
  { valueOP: ValueOP.LIFT_LIKE, label: '文本左包含(%#)' },
  { valueOP: ValueOP.RIGHT_LIKE, label: '文本右包含(#%)' },
  { valueOP: ValueOP.EXISTS, label: '存在(EXISTS)' },
  { valueOP: ValueOP.NOT_EXISTS, label: '不存在(NOTEXISTS)' },
] as const;

/** 不需要编辑器的OP */
export const ExcludeOPs: readonly string[] = [
  ValueOP.IS_NULL,
  ValueOP.IS_NOT_NULL,
] as const;

/**
 * 过滤项组件
 * - 用于设置过滤值的组件
 */
export const FilterItem = defineComponent({
  name: 'FilterItem',
  props: {
    showLabel: { type: Boolean, default: true },
    data: {
      type: Object as PropType<IFilterNodeField>,
      required: true,
    },
    model: {
      type: Object as PropType<ISearchBarFilter>,
      required: true,
    },
    controller: {
      type: Object as PropType<FilterSearchBarController>,
      required: true,
    },
  },
  emits: ['change'],
  setup(props, { emit }) {
    const ns = useNamespace('filter-item');
    const c = props.controller;

    const filterC = c.filterControllers.find(item => {
      return item.model.id === props.model.id;
    });

    /**
     * 可选操作符
     */
    const valueOPs = computed(() => {
      return filterC?.valueOP
        ? FilterModes.filter(item => item.valueOP === filterC.valueOP)
        : FilterModes;
    });

    /**
     * 初始化默认值
     *
     */
    const initData = (): void => {
      if (!props.data.valueOP) {
        props.data.valueOP = valueOPs.value[0].valueOP;
      }
    };

    initData();

    /**
     * 值操作模式选择变更
     * @param valueOP 操作模式
     */
    const onValueOPSelect = (valueOP: ValueOP): void => {
      props.data.valueOP = valueOP;
      // 修改条件的同时清空后面的值
      props.data.value = null;
      emit('change', { name: undefined, val: null });
    };

    /**
     * 绘制编辑器
     * @param node 过滤项数据
     * @param controller 过滤项控制器
     * @returns
     */
    const renderEditor = (
      node: IFilterNodeField,
      controller: SearchBarFilterController,
    ): JSX.Element | null => {
      if (
        controller.noEditor ||
        (node.valueOP && ExcludeOPs.includes(node.valueOP))
      ) {
        return null;
      }
      let editor: VNode | null = null;

      if (controller.editorProvider) {
        const { data, value } = controller.calcEditorProps(node);
        const editorProps = {
          key: controller.editor!.model.id,
          value: value as any,
          controller: controller.editor as any,
          disabled: node.disabled,
          data,
          onChange: (val: unknown, name?: string): void => {
            controller.onEditorChange(node, val, name);
            emit('change', { name, val });
          },
        };
        const editorName = controller.editorProvider.formEditor;
        if (editorName === 'IBizInput') {
          editor = <IBizInput {...editorProps}></IBizInput>;
        } else {
          const component = resolveComponent(editorName);
          editor = h(component, editorProps);
        }
      } else {
        editor = <not-supported-editor modelData={controller.model.editor} />;
      }
      return <div class={ns.em('cond', 'editor')}>{editor}</div>;
    };

    /**
     * 绘制内容
     *
     * @return {*}  {(JSX.Element | undefined)}
     */
    const renderContent = (): JSX.Element | undefined => {
      if (filterC) {
        return (
          <div class={ns.e('cond')}>
            {props.showLabel && (
              <div class={ns.em('cond', 'label')}>{filterC.label}</div>
            )}
            <div class={ns.em('cond', `op-style2`)}>
              <el-select
                class={ns.em('cond', 'mode')}
                model-value={props.data.valueOP}
                disabled={props.data.disabled}
                onChange={(valueOP: ValueOP) => {
                  onValueOPSelect(valueOP);
                }}
              >
                {valueOPs.value.map(mode => {
                  return (
                    <el-option
                      key={mode.valueOP}
                      value={mode.valueOP}
                      label={mode.label}
                    />
                  );
                })}
              </el-select>
              {renderEditor(props.data, filterC)}
            </div>
          </div>
        );
      }
    };
    return {
      ns,
      renderContent,
    };
  },
  render() {
    return <div class={this.ns.b()}>{this.renderContent()}</div>;
  },
});
export default FilterItem;
